package docker

import (
	"sync"
	"os"
	"bufio"
	"strings"
	"cloud_worm/util/ufile"
	"sync/atomic"
	"time"
	"github.com/golang/glog"
)

const (
	NormalHost = iota				// 普通机器
	DockerHost						// docker宿主机
	DockerContainer					// 容器
)

const (
	DockerdPath = "/usr/bin/dockerd"
	DockerPath = "/usr/bin/docker"

	loaded = 1
	unLoaded = 0
)

var ContainInfoInst = &ContainInfo{
	IPMap: make(map[string]string),
	loaded: unLoaded,
	loadC: make(chan struct{}, 10),							// 避免GetIPById中存在阻塞，所以容量设置为10
}

func init()  {
	ContainInfoInst.GetSystemType()
}


type ContainInfo struct {
	m 			sync.Mutex
	IPMap 		map[string]string
	SystemType 	int

	loaded 		int32
	loadC 		chan struct{}
}

func (d *ContainInfo) GetSystemType() error {
	fp, err := os.Open("/proc/1/cgroup")
	if err != nil {
		return err
	}
	defer fp.Close()

	scan := bufio.NewScanner(fp)
	for scan.Scan() {
		l := strings.TrimSpace(scan.Text())
		if len(l) <= 0 || strings.Contains(l, "debug") {
			continue
		}

		elems := strings.Split(l, ":")
		if len(elems) != 3 {
			continue
		}

		if elems[2] == "/" {
			if ufile.FileExists(DockerPath) || ufile.FileExists(DockerdPath) {
				d.SystemType = DockerHost
				return nil
			}

			d.SystemType = NormalHost
			return nil
		} else if strings.Contains(elems[2], "docker") {
			d.SystemType = DockerContainer
			return nil
		}
	}

	d.SystemType = NormalHost
	return nil
}

func (d *ContainInfo) GetIPById(id string) string {
	d.m.Lock()
	if v, exist := d.IPMap[id]; exist {
		d.m.Unlock()
		return v
	}
	d.m.Unlock()

	// map中没有该docker id，尝试触发load id ip map
	if atomic.LoadInt32(&d.loaded) == unLoaded {
		d.loadC <- struct{}{}
	}

	return ""
}

func (d *ContainInfo) LoadIdIPMap() error {
	// TODO：待实现加载ip和docker id的对应值
	return nil
}

func (d *ContainInfo) LoadLoop()  {
	// 30s内不允许第二次触发加载
	t := time.NewTimer(30 * time.Second)
	glog.Infof("Start load docker_map_id loop ......")

	for {
		select {
		case <- d.loadC:
			if atomic.LoadInt32(&d.loaded) == unLoaded {
				glog.Infof("doing loadIdIpMap")
				atomic.CompareAndSwapInt32(&d.loaded, unLoaded, loaded)			// 设置load
				d.LoadIdIPMap()							// 加载docker map
			}
			t.Reset(30 * time.Second)

		case <- t.C:
			// 30s超时，设置为0，表示没有load过
			atomic.CompareAndSwapInt32(&d.loaded, loaded, unLoaded)
			t.Reset(30 * time.Second)
		}
	}
}